const io = require("socket.io-client");
const EventEmitter = require('events');
const { compressFolder } = require("./fileService");
const { v4: uuidv4 } = require('uuid');
const filePackageSize = 10000;

const ACTION = {
    NEW_PROJECT: 'newProject',
    LIST_PROJECT: 'listProjects',
    NEW_VERSION: 'newVersion',
    FIND_PROJECT_BYID: 'findProjectById',
    // File
    FILE_PREUPLOAD: 'preupload',
    FILE_UPLOAD: 'upload',
    FILE_AFTERUPLOAD: 'afterupload'
}

class EventToPromiseProxy {
    constructor(cb) {
        this.promise = new Promise(this.promiseHandler);
        this.event = new EventEmitter();
        this.event.on()
    }
    promiseHandler(resolve, reject) {

    }
    callbackHandler(result) {
        //this.promise.re
    }
}

class Client {
    constructor(serverAddr) {
        this.socket = io(serverAddr);
        this.socket.on("connect", this.onConnectHandler);
    }
    //事件回调函数
    onConnectHandler = () => {
        const socket = this.socket;
        console.log("server connected:", socket.id);
    }
    onListProjectHandler = (projects) => {
        console.log('Projects ack:', projects);
    };
    onProjectDetailHandler = (project) => {
        console.log('Project detail ack:', project);
    };
    onNewProjectHandler = (project) => {
        console.log('add projects ack:', project);
    };
    onNewVersionHandler = (version) => {
        console.log('add version ack:', version);
    };
    callbackHandler = (handler, cb) => {
        if (cb) {
            return (result) => {
                cb(result);
            }
        } else {
            return handler;
        }
    }
    promiseHandler(resolveFunc) {
        return new Promise((resolve, reject) => {
            resolveFunc(resolve, reject);
        })
    }
    //查询所有项目
    findAllProject(filter) {
        console.log("find all peoject called. filter:", filter);
        return this.promiseHandler((resolve, reject) => {
            console.log("set timer");
            let timeOut = setTimeout(() => {
                console.log("Timeout!");
                reject({ success: false, errMsg: 'Timeout' })
            }, 30000);
            this.socket.emit(ACTION.LIST_PROJECT, { filter }, (result) => {
                clearTimeout(timeOut);
                resolve(result);
            });
        })
    }
    //获取项目明细
    getProjectDetail(projectId) {
        return this.promiseHandler((resolve, reject) => {
            console.log("get peoject called. filter:", projectId);
            console.log("set timer");

            let timeOut = setTimeout(() => {
                console.log("Timeout!");
                reject({ success: false, errMsg: 'Timeout' })
            }, 30000);
            this.socket.emit(ACTION.FIND_PROJECT_BYID, projectId, (result) => {
                clearTimeout(timeOut);
                resolve(result);
            });
        })
    }
    //添加新项目
    addNewProject(project) {
        project.description = this.parseVersionDescription(project.description);
        return this.promiseHandler((resolve, reject) => {
            console.log("add new peoject called. project:", project);
            console.log("set timer");

            let timeOut = setTimeout(() => {
                console.log("Timeout!");
                reject({ success: false, errMsg: 'Timeout' })
            }, 30000);
            this.socket.emit(ACTION.NEW_PROJECT, project, (result) => {
                console.log("add new project callback:", result);
                clearTimeout(timeOut);
                resolve(result);
            });
        })
    }

    parseVersionDescription(desc){
        if(desc && typeof(desc) === "string"){
            return desc.replace(/[\r\n]/,"<br/>");
        }
        return desc;
    }

    //添加新版本
    addNewVersion(version) {
        version.changeList = this.parseVersionDescription(version.changeList);

        return this.promiseHandler((resolve, reject) => {
            console.log("add new version called. version:", version);
            console.log("set timer");

            let timeOut = setTimeout(() => {
                console.log("Timeout!");
                reject({ success: false, errMsg: 'Timeout' })
            }, 30000);
            this.socket.emit(ACTION.NEW_VERSION, version, (result) => {
                clearTimeout(timeOut);
                resolve(result);
            });
        })
    }
    async compressPRFile(localFolder) {
        return compressFolder(localFolder);
    }
    //上传文件
    async uploadPRFile(projectId, versionId, fileData, filePath, cb) {
        let s = this.socket;
        let callbackHandler = this.callbackHandler;
        console.log("befor compress folder");

        let buffer = fileData;
        cb && cb({ 'type': 'update', msg: '压缩完成。' });

        let fileId = uuidv4();
        let PRFileData = { projectId, versionId, fileId, filePath, overwrite: false }
        //第一次通讯创建文件上传Buffer
        let rs = s.emit(ACTION.FILE_PREUPLOAD, PRFileData, (ack) => {
            console.log("ack pre upload", ack);
            if (ack.success) {
                for (let i = 0; i < buffer.length; i += 2000) {
                    let subBuf = buffer.subarray(i, i + 2000);
                    PRFileData.buffer = subBuf;
                    s.emit(ACTION.FILE_UPLOAD, PRFileData, (uploadack) => {
                        //console.log('upload ack:',uploadack,uploadack.data.totlSize,buffer.byteLength,buffer.length);
                        if (uploadack.success) {
                            //console.log('upload ack:',uploadack);
                            const percent = (uploadack.data.totlSize * 2000 / buffer.length * 100).toFixed(0);
                            cb && cb({ 'type': 'updatepercent', msg: '正在上传文件。', 'percent': percent });

                        }
                    });
                }
                s.emit(ACTION.FILE_AFTERUPLOAD, PRFileData, callbackHandler(() => { }, cb));
            } else {
                cb && cb('上传文件失败' + ack.errMsg)
            }
        });
        console.log("Event trig result:", rs);

    }

    
}

module.exports = Client;